package cn.zz.veggie.application.service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.stereotype.Service;

import cn.zz.comm.core.types.query.PageQuery;
import cn.zz.comm.core.types.result.PageResult;
import cn.zz.comm.helper.BizCommHelper;
import cn.zz.comm.util.CollectorUtil;
import cn.zz.comm.util.DateTimeUtil;
import cn.zz.veggie.application.assembler.UserQuoteAssembler;
import cn.zz.veggie.application.packer.UserQuotePacker;
import cn.zz.veggie.model.domain.Product;
import cn.zz.veggie.model.domain.Quote;
import cn.zz.veggie.model.domain.User;
import cn.zz.veggie.model.query.ProductQuery;
import cn.zz.veggie.model.query.QuoteQuery;
import cn.zz.veggie.persistence.repository.ProductRepository;
import cn.zz.veggie.persistence.repository.QuoteRepository;
import cn.zz.veggie.persistence.repository.UserRepository;
import cn.zz.veggie.web.types.dto.mgmt.MgmtQuoteQueryDto;
import cn.zz.veggie.web.types.dto.mgmt.MgmtUserQuotePriceDto;
import cn.zz.veggie.web.types.dto.mgmt.MgmtUserQuoteSaveDto;
import cn.zz.veggie.web.types.vo.mgmt.MgmtProductQuoteVo;
import cn.zz.veggie.web.types.vo.mgmt.MgmtQuoteVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author zhongq
 * @since 2024/5/22
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class QuoteAppService {

	private final QuoteRepository quoteRepository;
	private final ProductRepository productRepository;
	private final UserRepository userRepository;

	public PageResult<MgmtQuoteVo> adminGetList(MgmtQuoteQueryDto dto, PageQuery page) {
		List<Integer> productIds = productRepository.findIdsByName(dto.getProductName());
		if (productIds != null && productIds.isEmpty()) {
			return PageResult.of(page, Collections.emptyList());
		}
		QuoteQuery query = UserQuoteAssembler.buildAdminQuery(dto, productIds);
		List<Quote> quotes = quoteRepository.findByPage(query, page);
		Set<Integer> uids = CollectorUtil.bws(quotes, Quote::getUid);
		Set<Integer> pids = CollectorUtil.bws(quotes, Quote::getPid);
		Map<Integer, Product> productMap = productRepository.findByIds(pids);
		Map<Integer, User> userMap = userRepository.findByIds(uids);

		return PageResult.of(page, CollectorUtil.bwl(quotes, quote -> {
			Product product = productMap.get(quote.getPid());
			User user = userMap.get(quote.getUid());
			return UserQuotePacker.toMgmtUserQuoteVo(quote, product, user);
		}));
	}

	public void adminSaveQuote(MgmtUserQuoteSaveDto dto) {
		final Integer pid = dto.getPid();
		final Product product = productRepository.findById(pid);
		BizCommHelper.requireNoNull(product, pid.toString());
		final Integer uid = dto.getUid();
		final User user = userRepository.findById(uid);
		BizCommHelper.requireNoNull(user, uid.toString());
		Quote quote = quoteRepository.findByUidAndPid(uid, pid);
		quote = UserQuoteAssembler.createOrUpdate(quote, dto);
		quoteRepository.save(quote);
		// history
	}

	public void adminChangeQuote(MgmtUserQuotePriceDto dto) {
		final Quote quote = quoteRepository.findById(dto.getId());
		BizCommHelper.requireNoNull(quote, dto.getId().toString());
		quote.setPrice(dto.getPrice());
		quote.setUpdatedAt(DateTimeUtil.unixTime());
		quoteRepository.save(quote);
		// history
	}

	public List<MgmtProductQuoteVo> adminGetProductList(Integer uid, List<String> product) {
		final ProductQuery query = new ProductQuery();
		query.names = product;
		List<Product> products = productRepository.findByPage(query, PageQuery.all());
		List<Integer> productIds = CollectorUtil.bwl(products, Product::getId);
		Map<Integer, Integer> productQuote = quoteRepository.findProductQuote(uid, productIds);
		return CollectorUtil.bwl(products, p -> UserQuotePacker.toMgmtProdQuoteVo(p, productQuote.get(p.getId())));
	}
}